#! /usr/bin/env node
const puppeteer = require('puppeteer')
const path = require('path')
const fs = require('fs')
const program = require('commander')
const inquirer = require('inquirer')
const chalk = require('chalk')
const https = require('https')
const http = require('http')
const log = console.log

// log(chalk.cyan(consoler()));
program
  .version('1.0')
  .description('reptile images base on puppeteer')
  .option('-v, --version <version>', '', '1.0')
  .option('-k, --key [key]', "What's the keywords")
  .option('-n, --number [number]', 'How many images do you want?')
  .action(option => {
    let { key, number, version } = option
    log(chalk.yellow('------------------------'))
    log(chalk.red.bold(`Image repitle ${version}`))
    log(chalk.yellow('------------------------'))
    const question = []
    if (!key) {
      question.push({
        type: 'input',
        name: 'key',
        message: 'What are the keywords you are searching for?',
        validate: function(value) {
          return !!value || 'Please enter a valid Key'
        },
        filter: String
      })
    }
    if (!number) {
      question.push({
        type: 'input',
        name: 'number',
        message: 'How many images do you want?',
        validate: function(value) {
          let valid = !isNaN(parseInt(value))
          return valid || 'Please enter a valid Number'
        },
        filter: Number
      })
    }

    inquirer.prompt(question).then(answer => {
      repitle(answer)
    })
  })

/***
 * 页面滚动函数
 * */
async function autoScroll(page) {
  log(chalk.white('scrolling page'))
  await page.evaluate(() => {
    return new Promise((resolve, reject) => {
      let totalHeight = 0,
        distance = 100

      let timer = setInterval(() => {
        let docScrollHeight =
          document.body.scrollHeight || document.documentElement.scrollHeight
        window.scrollBy(0, distance)
        totalHeight += distance

        // 假设滚动到1000px就不去加载了
        if (totalHeight >= docScrollHeight) {
          clearInterval(timer)
          resolve()
        }
      }, 200)
    })
  })
}

/**
 * 主函数
 *  */

async function repitle(answer) {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.setViewport({ width: 2000, height: 1000 })
  await page.goto('https://image.baidu.com')
  await page.focus('#kw')
  await page.keyboard.sendCharacter(answer.key)
  await page.click('.s_search')

  page.on('load', async () => {
    if (answer.number > 20) {
      await autoScroll(page) // 先拉动页面滚动条
    }
    log(chalk.blue('Page has load over, start fetch images'))
    const result = await page.evaluate(() => {
      let elems = document.querySelectorAll('img.main_img')
      const srcs = Array.prototype.map.call(elems, img => img.src)
      return srcs
    })
    log(
      chalk.red(
        `Get ${result.length} images totally, start download ${
          answer.number
        } images`
      )
    )
    storeData(result, answer)
    await downloadImg(result, answer)
    await browser.close()
  })
}

/**
 * 存储数据
 * */

function storeData(res, answer) {
  fs.writeFile(
    `${__dirname}/data/${answer.key}.json`,
    JSON.stringify(res),
    err => {
      if (err) {
        console.log(err)
      }
      console.log('file has saved')
    }
  )
}

/**
 * 下载图片
 */
async function downloadImg(srcs, answer) {
  let number = answer.number,
    key = answer.key
  dir = path.join(`${__dirname}`, `/data/images/${key}`)
  fs.existsSync(dir) ? null : fs.mkdirSync(dir)
  for (let i = 0, len = srcs.length; i < len && i < number; i++) {
    if (/^http/.test(srcs[i])) {
      let mod = /^https:/.test(srcs[i]) ? https : http
      mod.get(srcs[i], res => {
        let ext = path.extname(srcs[i])
        let filePath = path.join(`${dir}`, `${i}${ext}`)
        let writeStream = fs.createWriteStream(filePath)
        res
          .pipe(writeStream)
          .on('finish', () => {
            log(filePath + '写入成功')
          })
          .on('error', err => {
            throw err
          })
      })
    } else {
      let match = /^data:(.*?);base64,(.+)$/.exec(srcs[i])
      try {
        let ext = match[1].split('/')[1].replace('jpeg', 'jpg')
        let filePath = path.join(`${__dirname}/data/images/`, `${i}.${ext}`)
        fs.writeFile(filePath, match[2], 'base64', err => {
          if (err) throw err
          console.log(filePath + '写入成功')
        })
      } catch (err) {
        console.log(err)
      }
    }
  }
}

program.parse(process.argv)
